﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

using System.Ext.Xml;
using System.Xml;
using System.IO;
using mfXmlSerializer.TestObjects;

namespace mfXmlSerializer.NetduinoPlus2.RawXmlSupport.TestApp
{
    /*
    start writing
    <?xml version="1.0" encoding="utf-8"?>
    <Parameter><Version>v.1.0</Version><Number>48</Number><Created>01/12/2014 13:12:00</Created><Logging><FileLoggingActive>true</FileLoggingActive><TraceLevel>1</TraceLevel></Logging></Parameter>
    98568 bytes available
    end writing
    start reading
    decl: xml, version="1.0" encoding="utf-8"
    element: Parameter
    element: Version
    text: v.1.0
    end element
    element: Number
    text: 48
    end element
    element: Logging
    element: FileLoggingActive
    text: true
    end element
    element: TraceLevel
    text: 1
    end element
    end element
    end element
    59952 bytes available
    end reading
    start reading
    59988 bytes available
    end reading
    The thread '<No Name>' (0x1) has exited with code 0 (0x0).
    Done.
     * */
    public class Program
    {
        public static void Main()
        {
            Debug.EnableGCMessages(true);

            //MFDqwsExtensions.dll in System.Ext.xml contains the XmlWriter
            //System.Xml.Legacy(.dll) in System.Xml contains the XmlReader (note new System.Xml(.dll) not working on netduino plus 2)
            //System.IO(.dll) in System.IO contains the MemoryStream
            //--> ~63 KB Deploymentspace 4 this sample

            var parameter = WriteTest();

            ReadTestDynamic(parameter);
            ReadTestTyped(parameter);
        }

        private static void ReadTestDynamic(byte[] parameter)
        {
            Debug.Print("start reading");
            var xmlReader = new MemoryStream(parameter);
            var readerSettings = new XmlReaderSettings() { IgnoreComments = true, IgnoreWhitespace = true, CheckCharacters = false };

            using (XmlReader reader = XmlReader.Create(xmlReader, readerSettings))
            {
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                        case XmlNodeType.Attribute://Attribute in legacy are not readed
                            Debug.Print("attribute: " + reader.Name);
                            break;
                        case XmlNodeType.Element:
                            Debug.Print("element: " + reader.Name);
                            break;
                        case XmlNodeType.Text:
                            Debug.Print("text: " + reader.Value);
                            break;
                        case XmlNodeType.XmlDeclaration:
                            Debug.Print("decl: " + reader.Name + ", " + reader.Value);
                            break;
                        case XmlNodeType.Comment:
                            Debug.Print("comment " + reader.Value);
                            break;
                        case XmlNodeType.EndElement:
                            Debug.Print("end element");
                            break;
                        case XmlNodeType.Whitespace:
                            Debug.Print("white space");
                            break;
                        case XmlNodeType.None:
                            Debug.Print("none");
                            break;
                        default:
                            Debug.Print(reader.NodeType.ToString());
                            break;
                    }
                }
            }
            xmlReader.Dispose();

            Debug.Print(Debug.GC(true) + " bytes available");
            Debug.Print("end reading");
        }

        private static void ReadTestTyped(byte[] parameter)
        {
            Debug.Print("start reading");
            var xmlReader = new MemoryStream(parameter);
            var readerSettings = new XmlReaderSettings() { IgnoreComments = true, IgnoreWhitespace = true, CheckCharacters = false };

            Parameter para = null;

            using (XmlReader reader = XmlReader.Create(xmlReader, readerSettings))
            {
                reader.Read();//skip xml header declaration or check it?!

                //read parameter start element
                reader.Read();
                if (reader.Name != "Parameter" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no Parameter element found");

                para = new Parameter();

                //read version element
                reader.Read();
                if (reader.Name != "Version" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no Parameter element found");

                //read version element text
                reader.Read();
                if (reader.NodeType != XmlNodeType.Text)
                    throw new Exception("no Version Text found");

                //use SetMethod here in fx
                para.Version = reader.Value;

                //read Version end element
                reader.Read();
                if (reader.Name != "Version" && reader.NodeType != XmlNodeType.EndElement)
                    throw new Exception("no Version end-element found");

                //read Number element
                reader.Read();
                if (reader.Name != "Number" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no Number element found");

                //read Number element text
                reader.Read();
                if (reader.NodeType != XmlNodeType.Text)
                    throw new Exception("no Number Text found");

                //use SetMethod here in fx
                para.Number = Convert.ToInt32(reader.Value);

                //read Number end element
                reader.Read();
                if (reader.Name != "Number" && reader.NodeType != XmlNodeType.EndElement)
                    throw new Exception("no Number end-element found");

                //--
                //read Created element
                reader.Read();
                if (reader.Name != "Created" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no Created element found");

                //read Created element text
                reader.Read();
                if (reader.NodeType != XmlNodeType.Text)
                    throw new Exception("no Created Text found");

                para.Created = ConvertToDateTime(reader.Value);

                //read Created end element
                reader.Read();
                if (reader.Name != "Created" && reader.NodeType != XmlNodeType.EndElement)
                    throw new Exception("no Created end-element found");
                //--

                //read Logging start element
                reader.Read();
                if (reader.Name != "Logging" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no Logging element found");

                //read FileLoggingActive element
                reader.Read();
                if (reader.Name != "FileLoggingActive" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no FileLoggingActive element found");

                //read FileLoggingActive element text
                reader.Read();
                if (reader.NodeType != XmlNodeType.Text)
                    throw new Exception("no FileLoggingActive Text found");

                //set FileLoggingActive
                bool value = (reader.Value == "true") ? true : false;
                para.LogConfig.FileLoggingActive = value;

                //read FileLoggingActive end element
                reader.Read();
                if (reader.Name != "FileLoggingActive" && reader.NodeType != XmlNodeType.EndElement)
                    throw new Exception("no FileLoggingActive end-element found");

                //read TraceLevel element
                reader.Read();
                if (reader.Name != "TraceLevel" && reader.NodeType != XmlNodeType.Element)
                    throw new Exception("no TraceLevel element found");

                //read TraceLevel element text
                reader.Read();
                if (reader.NodeType != XmlNodeType.Text)
                    throw new Exception("no TraceLevel Text found");

                //set TraceLevel
                enumTraceLevel traceLevel = (enumTraceLevel)Convert.ToInt32(reader.Value);
                para.LogConfig.TraceLevel = traceLevel;

                //read Logging end element
                reader.Read();
                if (reader.Name != "Logging" && reader.NodeType != XmlNodeType.EndElement)
                    throw new Exception("no Logging end-element found");

                //read Parameter end element
                reader.Read();
                if (reader.Name != "Parameter" && reader.NodeType != XmlNodeType.EndElement)
                    throw new Exception("no Parameter end-element found");

            }

            Debug.Print(Debug.GC(true) + " bytes available");
            Debug.Print("end reading");
        }

        private static DateTime ConvertToDateTime(string value)
        {
            //"MM/dd/yyyy HH:mm:ss";
            var spaceSplit = value.Split(new char[] { ' ' }, 2);

            var dateSplit = spaceSplit[0].Split(new char[] { '/' }, 3);
            var timeSplit = spaceSplit[1].Split(new char[]{':'}, 3);

            return new DateTime(Convert.ToInt32(dateSplit[2])//year
                                , Convert.ToInt32(dateSplit[0])//month
                                , Convert.ToInt32(dateSplit[1])//day
                                , Convert.ToInt32(timeSplit[0])//hour
                                , Convert.ToInt32(timeSplit[1])//minute
                                , Convert.ToInt32(timeSplit[2]));//second
        }

        private static byte[] WriteTest()
        {

            Debug.Print("start writing");
            //http://netmf.codeplex.com/workitem/1054 
            var memWriter = new MemoryStream();
            var xmlwrite = XmlWriter.Create(memWriter);
            xmlwrite.WriteProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");

            xmlwrite.WriteStartElement("Parameter");

				//Note: Leaf Attribute serialization worked but XmlReader skips attribute
				//...e.g.: xmlwrite.WriteAttributeString("Version", "v.1.0");
				xmlwrite.WriteElementString("Version", "v.1.0");
                xmlwrite.WriteElementString("Number", "48");
                xmlwrite.WriteElementString("Created", "01/12/2014 13:12:00");


				xmlwrite.WriteStartElement("Logging");

					xmlwrite.WriteElementString("FileLoggingActive", "true");
					xmlwrite.WriteElementString("TraceLevel", "1");//Debug-Level

				xmlwrite.WriteEndElement();

            xmlwrite.WriteEndElement();
            //end writing
            xmlwrite.Flush();
            xmlwrite.Close();

            var s = DisplayMemoryStream(memWriter);
            xmlwrite.Dispose();

            Debug.Print(Debug.GC(true) + " bytes available");
            Debug.Print("end writing");

            return s;
        }

        private static byte[] DisplayMemoryStream(MemoryStream ms)
        {
            byte[] byteArray = ms.ToArray();
            char[] cc = System.Text.UTF8Encoding.UTF8.GetChars(byteArray);
            string str = new string(cc);
            Debug.Print(str);
            return byteArray;
        }

    }
}
